Conversation
c615454 to
d71c885
Compare
|
Claude finished @varex83's task in 3m 54s —— View job Code Review
SummaryThis PR erases the Findings[High]
|
| Component | Go | Rust | Match | Notes |
|---|---|---|---|---|
store_internal |
present | present | yes | |
store_external |
present | present | yes | |
trim (cleanup loop) |
present | present | yes | |
| Duplicate share_idx detection | present | present | yes | |
| Mismatch error | present | present | yes | |
| Threshold matching (exact vs >=) | TBD | exact | ? | Needs Go ref to confirm |
keys_by_duty dedup |
yes (Go uses a Set) | no | no | Bug: see finding #1 |
Tests
Tests in memory_internal_test.rs cover: threshold matching with multiple variants, full lifecycle with deadliner expiry, and both SyncCommitteeMessage and BeaconCommitteeSelection types. Good coverage overall.
|
Shouldn't it be parsigdb (without addional 'a')? |
| pub struct ParSignedData { | ||
| /// Partially signed duty data. | ||
| pub signed_data: T, | ||
| pub signed_data: Box<dyn SignedData>, |
There was a problem hiding this comment.
There is one usages in charon, which downcast the signed_data, storing Box<dyn SignedData> could not downcast this.
attVidx, ok := parSig.SignedData.(core.VersionedAttestation)
There was a problem hiding this comment.
Could you share what was discussed during daily @varex83 ?
There was a problem hiding this comment.
It was fixed in the #291 by using std::any::Any with downcast_ref to serialize / deserialize objects
emlautarom1
left a comment
There was a problem hiding this comment.
LGTM, minor stuff only
| pub fn random_eth2_signature() -> String { | ||
| let mut bytes = [0u8; 96]; | ||
| let mut rng = rand::thread_rng(); | ||
| for byte in &mut bytes { | ||
| *byte = rng.r#gen(); | ||
| } | ||
| format!("0x{}", hex::encode(bytes)) | ||
| } |
There was a problem hiding this comment.
nit: why not reuse the code from random_eth2_signature_bytes?
| pub fn random_eth2_signature() -> String { | |
| let mut bytes = [0u8; 96]; | |
| let mut rng = rand::thread_rng(); | |
| for byte in &mut bytes { | |
| *byte = rng.r#gen(); | |
| } | |
| format!("0x{}", hex::encode(bytes)) | |
| } | |
| pub fn random_eth2_signature() -> String { | |
| let bytes = random_eth2_signature_bytes(); | |
| format!("0x{}", hex::encode(bytes)) | |
| } |
crates/testutil/src/random.rs
Outdated
| // Check format | ||
| assert!(bitlist.starts_with("0x")); | ||
| // 32 bytes = 64 hex chars + "0x" prefix = 66 total | ||
| assert_eq!(bitlist.len(), 66); |
There was a problem hiding this comment.
We should check that it actually results in only 5 bits set
| assert_eq!(bitlist.len(), 66); | |
| assert_eq!(bitlist.len(), 66); | |
| // Decode to bytes | |
| let bytes = hex::decode(&bitlist[2..]).unwrap(); | |
| // Check that at least 5 bits are set | |
| let bit_count = bytes.iter().map(|b| b.count_ones()).sum::<u32>(); | |
| assert_eq!(bit_count, 5); |
There was a problem hiding this comment.
nit: we could parametrize the test to test with multiple lengths (ex. 0, 5, 50, 256)
crates/core/src/signeddata.rs
Outdated
| /// Custom error. | ||
| #[error("{0}")] | ||
| Custom(Box<dyn std::error::Error>), |
crates/core/src/testutils.rs
Outdated
| /// The size of a BLS public key in bytes. | ||
| const PK_LEN: usize = 48; |
There was a problem hiding this comment.
This constant is duplicated in crates/core/src/types.rs. We can reference it instead of duplicating it.
crates/core/src/testutils.rs
Outdated
| pub fn new_seed_rand() -> impl Rng { | ||
| let seed = rand::random::<u64>(); | ||
| rand::rngs::StdRng::seed_from_u64(seed) | ||
| } |
There was a problem hiding this comment.
No need for this code, just use a default random generator.
Note: I remember you mentioning that now Claude is overly strict with porting. This is a clear case of that.
crates/core/src/testutils.rs
Outdated
| /// This should never happen in practice as we generate exactly 48 bytes. | ||
| pub fn random_core_pub_key_seed<R: Rng>(mut rng: R) -> PubKey { | ||
| let pubkey = deterministic_pub_key_seed(&mut rng); | ||
| PubKey::try_from(&pubkey[..]).expect("valid pubkey length") |
There was a problem hiding this comment.
No need for try_from and expect:
| PubKey::try_from(&pubkey[..]).expect("valid pubkey length") | |
| PubKey::from(pubkey) |
crates/core/src/testutils.rs
Outdated
| // Fill the key with random bytes | ||
| for byte in &mut key { | ||
| *byte = seeded_rng.r#gen(); | ||
| } |
There was a problem hiding this comment.
nit: Use fill_bytes:
| // Fill the key with random bytes | |
| for byte in &mut key { | |
| *byte = seeded_rng.r#gen(); | |
| } | |
| // Fill the key with random bytes | |
| seeded_rng.fill_bytes(&mut key); |
| pub struct ParSignedData { | ||
| /// Partially signed duty data. | ||
| pub signed_data: T, | ||
| pub signed_data: Box<dyn SignedData>, |
There was a problem hiding this comment.
Could you share what was discussed during daily @varex83 ?
Closes #274
This PR adds two new dependencies:
dyn-clone- allows cloning trait objects such asSignedDatadyn-eq- allows comparing trait objects such asSignedDataThey make it possible to clone and compare
Box<dyn SignedData>directly. Using them, rather than adding custom clone/equality methods and plumbing for each type, saved a lot of development time.I’d also like to request allowing
dyn-eqincargo deny. It can throw the errors due to the license (MPL)